package com.nineclock.attendance.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nineclock.attendance.dto.AttendGroupDTO;
import com.nineclock.attendance.dto.AttendGroupPCExtraConfigDTO;
import com.nineclock.attendance.dto.AttendGroupPartDTO;
import com.nineclock.attendance.dto.AttendPunchDTO;
import com.nineclock.attendance.mapper.AttendGroupMapper;
import com.nineclock.attendance.mapper.AttendGroupPartMapper;
import com.nineclock.attendance.pojo.AttendGroup;
import com.nineclock.attendance.pojo.AttendGroupPart;
import com.nineclock.attendance.pojo.AttendPunch;
import com.nineclock.attendance.service.AttendGroupService;
import com.nineclock.common.entity.PageResult;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.threadlocal.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.system.feign.SysOrganizationFeign;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


@Service
@Slf4j
@Transactional
public class AttendGroupServiceImpl implements AttendGroupService {
    @Autowired
    AttendGroupMapper attendGroupMapper;
    @Autowired
    SysOrganizationFeign organizationFeign;
    @Autowired
    AttendGroupPartMapper attendGroupPartMapper;


    /**
     * 1. 干什么: 此处来写查询
     * 2. 怎么查
     * 2.1 判断是否初次使用, 如初次使用,则初始化默认考勤组
     * 2.2 默认考勤组关联 部门   关系维护
     * 3. 考勤的分页查询
     * 4. 考勤组关联的员工数量
     * 5.组装数据并返回
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageResult<AttendGroupDTO> queryAttendGroupPage(Integer page, Integer pageSize) {
        //1.判断是否初次使用,如果初次使用 则初始化默认考勤组
        LambdaQueryWrapper<AttendGroup> attendGroupQw = new LambdaQueryWrapper<>();
        attendGroupQw.eq(AttendGroup::getCompanyId, CurrentUserHolder.get().getCompanyId());

        Integer count = attendGroupMapper.selectCount(attendGroupQw);
        //如果count=0的话说明 考勤组初次使用
        if (count==0) {
            //初始化默认考勤组
//            AttendGroup attendGroup = new AttendGroup();
            AttendGroup attendGroup = this.buildDefaultAttendGroup();

            //新增考勤组到数据库
            attendGroupMapper.insert(attendGroup);
            //获取所有的一级部门
            List<Long> departmentIds = organizationFeign.queryDepartmentIds().getData();
            //每个部门都需要关联, 循环每个部门
            if (CollectionUtil.isNotEmpty(departmentIds)) {
                for (Long departmentId : departmentIds) {

                    AttendGroupPart attendGroupPart = new AttendGroupPart();
                    attendGroupPart.setAttendGroupId(attendGroup.getId());//考勤组id
                    attendGroupPart.setObjectType(1);//对象类型
                    attendGroupPart.setObjectId(departmentId);//对象id(部门,或者用户)
                    attendGroupPart.setAttendType(1);//考勤类型(是否参加考勤1 or 0)

                    //考勤组需要跟部门或者员工有关系
                    //获取所有一级部门
                    attendGroupPartMapper.insert(attendGroupPart);
                }
            }
        }
        //分页查询
        Page<AttendGroup> attendGroupPage = new Page<>(page,pageSize);
        attendGroupQw = new LambdaQueryWrapper<>();
        attendGroupQw.eq(AttendGroup::getCompanyId,CurrentUserHolder.get().getCompanyId());
        //分页查询,获取分页结果对象
        attendGroupPage = attendGroupMapper.selectPage(attendGroupPage,attendGroupQw);
        //当前页要展示的数据
        List<AttendGroup> records = attendGroupPage.getRecords();
        if (CollectionUtil.isNotEmpty(records)) {
            //如果records 不为null 则转换为DTO对象

            List<AttendGroupDTO> attendGroupDTOS = BeanHelper.copyWithCollection(records, AttendGroupDTO.class);
            for (AttendGroupDTO attendGroupDTO : attendGroupDTOS) {
                //查询 考勤组 与部门和员工的关系
                LambdaQueryWrapper<AttendGroupPart> attendGroupPartQw = new LambdaQueryWrapper<>();
                attendGroupPartQw.eq(AttendGroupPart::getAttendGroupId,attendGroupDTO.getId());
                //获取该考勤组的关系列表
                List<AttendGroupPart> attendGroupPartList = attendGroupPartMapper.selectList(attendGroupPartQw);
                //filter: 返回值为boolean , 如果为true 则包含数据,false 则不包含数据
                //统计关系表中的部门类型的数据
                List<Long> departmentIds = attendGroupPartList.stream().filter(attendGroupPart -> {
                    if (attendGroupPart.getObjectType() == 1) {
                        return true;
                    }
                    return false;
                }).map(attendGroupPart -> {
                    return attendGroupPart.getObjectId();
                }).collect(Collectors.toList());
                //统计关系表中的员工的id
                List<Long> userIds = attendGroupPartList.stream().filter(attendGroupPart -> {
                    return attendGroupPart.getObjectType()==2;
                }).map(attendGroupPart -> {
                    return attendGroupPart.getObjectId();
                }).collect(Collectors.toList());
                //查询部门对应的员工数量
                if (CollectionUtil.isNotEmpty(departmentIds)) {
                    Integer departmentUserCount = organizationFeign.queryUserCountByDepartmentIds(departmentIds).getData();
                    attendGroupDTO.setMemberNum((userIds == null ? 0:userIds.size()) + departmentUserCount);
                }






                //设置员工的数量 userId.size() + 部门下的员工数量


            }
            return new PageResult(attendGroupPage.getTotal(),attendGroupPage.getPages(),attendGroupDTOS);
        }

        return new PageResult();

    }



                       /* 考勤组                 添加 */

    @Override
    public void addAttendGroup(AttendGroupDTO attendGroupDTO) {
        if (attendGroupDTO == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        //BeanHelper 只能复制相同类型,相同属性名的字段
        //最终往数据库加的一定是AttendGroup对象 所以把AttendGroup转换成pojo对象
        AttendGroup attendGroup = BeanHelper.copyProperties(attendGroupDTO, AttendGroup.class);
        //工作日 设置
        List<String> workdays = attendGroupDTO.getWorkdays();
        //用什么来间隔 用","  转成字符串
        String workdaysStr = StrUtil.join(",", workdays.toArray());
        attendGroup.setWorkdays(workdaysStr);
        //设置基本信息 当前登录的员工
        attendGroup.setCreateUserId(CurrentUserHolder.get().getCompanyUserId());
        attendGroup.setCreateTime(new Date());
        attendGroup.setCompanyId(CurrentUserHolder.get().getCompanyId());

        //需要打卡的日期列表
        List<String> necessaryTime = new ArrayList<>();
        //无需打卡的日期列表
        List<String> unNecessaryTime = new ArrayList<>();
        //设置需要打卡 和无需打卡的日期

        List<AttendGroupPCExtraConfigDTO> extraConfig = attendGroupDTO.getExtraConfig();
        for (AttendGroupPCExtraConfigDTO attendGroupPCExtraConfigDTO : extraConfig) {
            if (attendGroupPCExtraConfigDTO.getRequiredAttend()==1) {
                necessaryTime.add(attendGroupPCExtraConfigDTO.getSetDate());

            }else {
                unNecessaryTime.add(attendGroupPCExtraConfigDTO.getSetDate());

            }
        }

        //设置需要打卡的日期列表
        attendGroup.setNecessaryTimeList(StrUtil.join(",",necessaryTime));
        //设置无需打卡的日期列表
        attendGroup.setUnnecessaryTimeList(StrUtil.join(",",unNecessaryTime));


        //新增考勤组
        attendGroupMapper.insert(attendGroup);
        //维护考勤组 和部门, 员工之间的关系
        //获取需要考勤的信息
        List<AttendGroupPartDTO> participates = attendGroupDTO.getParticipates();
        if (CollectionUtil.isNotEmpty(participates)) {
            for (AttendGroupPartDTO participate : participates) {
                // //先删除 员工与其他考勤组的关系
                LambdaQueryWrapper<AttendGroupPart> attendGroupPartQw = new LambdaQueryWrapper<>();
                //设置 类型 (员工,部门)
                attendGroupPartQw.eq(AttendGroupPart::getObjectType,participate.getObjectType());
                //设置类型 部门或者员工的id
                attendGroupPartQw.eq(AttendGroupPart::getObjectId,participate.getObjectId());
                //设置是否参与考勤
//                attendGroupPartQw.eq(AttendGroupPart::getAttendType,1);
                //删除原来的关系
                attendGroupPartMapper.delete(attendGroupPartQw);

                //维护新的关系
                AttendGroupPart attendGroupPart = new AttendGroupPart();
                attendGroupPart.setAttendGroupId(attendGroup.getId());
                attendGroupPart.setObjectType(participate.getObjectType());
                attendGroupPart.setObjectId(participate.getObjectId());
                attendGroupPart.setAttendType(1);

                attendGroupPartMapper.insert(attendGroupPart);

            }
        }





        //获取无需考勤的信息
        List<AttendGroupPartDTO> notParticipates = attendGroupDTO.getNotParticipates();

        if (CollectionUtil.isNotEmpty(notParticipates)) {
            for (AttendGroupPartDTO participate : notParticipates) {

                // //先删除 员工与其他考勤组的关系
                LambdaQueryWrapper<AttendGroupPart> attendGroupPartQw = new LambdaQueryWrapper<>();
                //设置 类型 (员工,部门)
                attendGroupPartQw.eq(AttendGroupPart::getObjectType,participate.getObjectType());
                //设置类型 部门或者员工的id
                attendGroupPartQw.eq(AttendGroupPart::getObjectId,participate.getObjectId());
                //设置是否参与考勤
//                attendGroupPartQw.eq(AttendGroupPart::getAttendType,2);
                //删除原来的关系
                attendGroupPartMapper.delete(attendGroupPartQw);

                //维护新的关系
                AttendGroupPart attendGroupPart = new AttendGroupPart();
                attendGroupPart.setAttendGroupId(attendGroup.getId());
                attendGroupPart.setObjectType(participate.getObjectType());
                attendGroupPart.setObjectId(participate.getObjectId());
                attendGroupPart.setAttendType(2);

                attendGroupPartMapper.insert(attendGroupPart);

            }
        }


    }











    private AttendGroup buildDefaultAttendGroup() {

        AttendGroup attendGroup = new AttendGroup();
        attendGroup.setName("默认考勤组");
        attendGroup.setCompanyId(CurrentUserHolder.get().getCompanyId());
        attendGroup.setStartWorkTime("09:00:00");
        attendGroup.setAllowLateMinutes(10);
        attendGroup.setLateMinutes(30);
        attendGroup.setStartNoonRestTime("12:00:00");
        attendGroup.setEndNoonRestTime("14:00:00");
        attendGroup.setOffWorkTime("18:00:00");
        attendGroup.setWorkdays("1,1,1,1,1,0,0");

        attendGroup.setAddress("金燕龙办公楼");
        attendGroup.setAddressName("金燕龙总部");
        attendGroup.setLat(new BigDecimal(116.343368));
        attendGroup.setLng(new BigDecimal(40.060456));
        attendGroup.setAddressRange(1000);
        attendGroup.setCreateUserId(CurrentUserHolder.get().getCompanyUserId());
        attendGroup.setCreateTime(new Date());


        return attendGroup;
    }
}
